package org.sgx.gwtjsutiljsfcgenerator;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.LinkedList;
import java.util.List;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

/**
 * single class file generator. Generate a JSFC code from a method Signature like "NN" - function accepting a number and returning a number.
 * 
 * @author sg
 * 
 */
public class SingleGenerator {
	public void generate(StringWriter w, String sig) throws BadSignature {
		JSFCContext ctx = generateContext(sig);
		
		Velocity.init();
		
        VelocityContext context = new VelocityContext();
        context.put("ctx", ctx);
        
        
        /* lets make our own string to render */

//        String s = "We are using $project $name to render this.";
        String resName="/org/sgx/gwtjsutiljsfcgenerator/tmpl/jsfc.vm"; 
        InputStream is = SingleGenerator.class.getResourceAsStream(resName);
//        w = new StringWriter();
        
        Velocity.evaluate( context, w, "mystring", is );
//        System.out.println(" string : " + w );
	}
	
	private JSFCContext generateContext(String sig) throws BadSignature {
		if (sig == null || sig.length() < 2)
			throw new BadSignature("signature must be at least 2 chars long. Given was: " + sig);
		sig = sig.toUpperCase();

		String returnType = sig.substring(0, 1);
		String returnType2 = toJavaType(returnType);
		List<String> paramType = new LinkedList<String>();
		List<String> paramType2 = new LinkedList<String>();
		String s = sig;
//		if(s.substring(1,s.length()).contains("V"))
//			throw new BadSignature("invalid signature V param not the first: "+sig);
		for (int i = 1; i < sig.length(); i++) {
			s = sig.substring(i, s.length());
			if(s.equals("V") && i>1)
				throw new BadSignature("invalid signature V param not the first: "+sig);
			
			if (s == null || s.length() == 0)
				break;
			String name = s.substring(0, 1);
			paramType.add(name);
			String jt = s.equals("V") ? "":toJavaType(name); 
			paramType2.add(jt); 
		}

		JSFCContext ctx = new JSFCContext();
		ctx.setReturnType(returnType2);
		
		ctx.setParamType(paramType2);
		ctx.setClassName(sig); 
		return ctx;
	}

	public String toJavaType(String t) throws BadSignature {
		if (t == null || t.length() != 1)
			throw new BadSignature("invalid individual type: " + t);
		if (t.equals("V"))
			return "void";
		else if (t.equals("N"))
			return "double";
		else if (t.equals("S"))
			return "String";
		else if (t.equals("B"))
			return "boolean";
		else if (t.equals("O"))
			return "JavaScriptObject";
		else
			throw new BadSignature("invalid individual type: " + t);

	}
}
